package com.gin.kotlin.no_gay_alliance.base

import android.util.Log
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.booleanPreferencesKey
import androidx.datastore.preferences.core.doublePreferencesKey
import androidx.datastore.preferences.core.floatPreferencesKey
import androidx.datastore.preferences.core.intPreferencesKey
import androidx.datastore.preferences.core.stringPreferencesKey
import androidx.datastore.preferences.core.stringSetPreferencesKey
import androidx.datastore.rxjava3.RxDataStore
import io.reactivex.rxjava3.core.Single
import kotlinx.coroutines.ExperimentalCoroutinesApi


/**
 * 命名的Datastore(工具类)，封装Datastore
 */
class NamedDataStore private constructor(private val dataStore: RxDataStore<Preferences>) {

    /**
     * 获取值
     * @param key String
     * @param defaultValue 默认值
     * @return Single<Preferences>
     */
    fun <T : Any> get(key: String, defaultValue: T) = dataStore.getValue(getPreferencesKey(key, defaultValue), defaultValue)

    /**
     * 设置值
     * @param key String
     * @param value T
     * @return Single<Preferences>
     */
    fun <T : Any> set(key: String, value: T) = dataStore.setValue(getPreferencesKey(key, value), value).also {
        Log.d(TAG, "设置值: $key")
    }

    /**
     * 移除值
     * @param key String
     * @param value T
     * @return Single<Preferences>
     */
    @OptIn(ExperimentalCoroutinesApi::class)
    fun <T : Any> remove(key: String, value: T) = dataStore.removeValue(getPreferencesKey(key, value)).also {
        Log.d(TAG, "移除值: $key")
    }


    /**
     * 清空所有值
     * @return Single<Preferences>
     */
    @OptIn(ExperimentalCoroutinesApi::class)
    fun clear() = dataStore.updateDataAsync { Single.just(it.toMutablePreferences().also { p -> p.clear() }) }

    companion object {
        private val TAG = NamedDataStore::class.java.simpleName

        /**
         * 默认的Datastore名称
         */
        private const val DEFAULT_STORE = "default_store"

        /**
         * 通过单例模式创建Datastore
         * @param name 名称，可以按用户区分
         * @return NamedDataStore
         */
        fun getInstance(name: String = DEFAULT_STORE) = NamedDataStore(DatastoreUtils.obtain(name))

        /**
         * 根据value值的类型返回 Preferences.Key
         *
         * @param key   key
         * @param value value
         * @param <T>   值类型
         * @return [Preferences.Key]
        </T> */
        private fun <T : Any> getPreferencesKey(key: String, value: T): Preferences.Key<T> {
            @Suppress("UNCHECKED_CAST") return when (value) {
                is String -> stringPreferencesKey(key)
                is Int -> intPreferencesKey(key)
                is Long -> intPreferencesKey(key)
                is Float -> floatPreferencesKey(key)
                is Double -> doublePreferencesKey(key)
                is Boolean -> booleanPreferencesKey(key)
                is Set<*> -> stringSetPreferencesKey(key)
                else -> throw RuntimeException("不支持的类型:" + value.javaClass.name)
            } as Preferences.Key<T>
        }
    }
}